package main

import "fmt"

/**
在go语言中数组是不常用的，常用的就是本节将说明了切片
根据官方给的文档说明切片其实就是数组的一个视图，因为切片还是要看array的
*/

func updateSlice(s []int) {
	s[0] = 100
}

/**
slice的扩展
*/
func extendSlice() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	s1 := arr[2:6]
	s2 := s1[3:5]
	// s1的值为 [2 3 4 5]
	fmt.Println("s1的值为", s1)
	// s2的值为 [5 6]  这里为什么会打印出来值？
	fmt.Println("s3的值为", s2)

	/**
	s1的值为 [2 3 4 5]   s2的值为 [5 6]
	slice可以向后扩展，不可以向前扩展
	s[i] 不可以超越 len(s),向后扩展不可以超越底层数组cap(s)
	这里的原理是在3-2切片的概念
	*/

	fmt.Println("slice extent")
	// s1=[2 3 4 5],len(s1)=4,cap(s1)=6
	fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
	// s2=[5 6],len(s2)=2,cap(s2)=3
	fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n", s2, len(s2), cap(s2))

	// 那么此时改变一下s1的值
	// [5 6 7]
	fmt.Println(s1[3:6])
	// 报错信息slice bounds out of range [:7] with capacity 6，由此可以验证slice可以向后扩展，不可以向前扩展
	//	s[i] 不可以超越 len(s),向后扩展不可以超越底层数组cap(s)
	//fmt.Println(s1[3:7])

	/**
	slice的操作，在s2 = [5,6]的基础上
	*/
	fmt.Println("Slice的扩容")
	s3 := append(s2, 10)
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	// s3,s4,s5 [5 6 10] [5 6 10 11] [5 6 10 11 12]
	fmt.Println("s3,s4,s5", s3, s4, s5)
	// arr =  [0 1 2 3 4 5 6 10] 在这里s4和s5不在是以arr为视图
	fmt.Println("arr = ", arr)

	/**
	总结：
	添加元素时如果超越cap，系统会重新分配更大的底层数组
	由于值传递的关系，必须接收append的返回值
	*/
}

func main() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	// arr[2:6] = [2 3 4 5]
	fmt.Println("arr[2:6] =", arr[2:6])
	// arr[2:6] = [0 1 2 3 4 5]
	fmt.Println("arr[2:6] =", arr[:6])
	// arr[2:6] = [2 3 4 5 6 7]
	fmt.Println("arr[2:6] =", arr[2:])
	// arr[2:6] = [0 1 2 3 4 5 6 7]
	fmt.Println("arr[2:6] =", arr[:])

	// 在这里写个案例
	s1 := arr[2:]
	fmt.Println("After updateSlice(s1)")
	updateSlice(s1)
	// [100 3 4 5 6 7]
	fmt.Println(s1)
	// [0 1 100 3 4 5 6 7]
	/*
		slice本身没有数据，是对底层array的一个view
	*/
	fmt.Println(arr)

	extendSlice()
}
